package org.finmanager.budget;

import com.alee.laf.button.WebButton;
import com.alee.laf.progressbar.WebProgressBar;

import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.GregorianCalendar;

import static org.finmanager.core.Constants.TABLE_COLUMN_COLOR1;
import static org.finmanager.core.Constants.TABLE_COLUMN_COLOR2;
import static org.finmanager.core.Constants.DATE_FORMAT_MONTH;

/**
 * Created by Kelvin on 4/4/2014.
 */

//The layout of the planning function
//It mainly involves a TABLE and some BUTTONS
public class BudgetManagerUI {
	private JPanel mainPanel = new JPanel();

	//the table showing budget with rows and columns
	private JTable table;

	//representing the "+" button
	private WebButton addBudgetButton = new WebButton("+");

	private BudgetPopupMenu budgetPopupMenu;

	//the style of the table
	public BudgetManagerUI(BudgetManagerController budgetManagerController) {
		table = new JTable(budgetManagerController.getBudgetModel().getBudgetTableModel());

		table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		table.setColumnSelectionAllowed(false);

		table.getTableHeader().setReorderingAllowed(false);
		table.getTableHeader().setResizingAllowed(false);

		table.setShowGrid(false);
		table.setIntercellSpacing(new Dimension(0,0));

		table.setRowHeight(30);

		table.setDefaultRenderer(Object.class, new BudgetTableRenderer());
		table.setDefaultRenderer(Integer.class, new BudgetRatioRenderer());
		table.setDefaultRenderer(GregorianCalendar.class, new DateRenderer());

		TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(table.getModel());
		table.setRowSorter(sorter);

		sorter.setSortable(BudgetTableModel.CATEGORY, false);
		sorter.setSortable(BudgetTableModel.DATE, false);
		sorter.setSortable(BudgetTableModel.RATIO, false);

		ArrayList<RowSorter.SortKey> list = new ArrayList<RowSorter.SortKey>();
		list.add(new RowSorter.SortKey(BudgetTableModel.DATE, SortOrder.DESCENDING));
		sorter.setSortKeys(list);
		sorter.sort();


		TableColumn column;
		for (int i = 0; i < table.getColumnCount(); ++i) {
			column = table.getColumnModel().getColumn(i);
			if (i == BudgetTableModel.RATIO)
				column.setPreferredWidth(250);
		}

		table.removeColumn(table.getColumnModel().getColumn(BudgetTableModel.REMAINING));
		table.removeColumn(table.getColumnModel().getColumn(BudgetTableModel.AMOUNT));

		table.addMouseListener(new TableMouseAdapter(table));

		budgetPopupMenu = new BudgetPopupMenu();

		table.setComponentPopupMenu(budgetPopupMenu);


		//the scroll tool on the right hand side
		JScrollPane scrollPane = new JScrollPane(table);
		scrollPane.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.DARK_GRAY));

		JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));

		addBudgetButton.setActionCommand(BudgetManagerController.OPEN_BUDGET_INPUT_UI);
		addBudgetButton.setDrawFocus(false);

		//the "+" button
		topPanel.add(addBudgetButton);

		getMainComponent().setLayout(new BorderLayout(0, 0));
		getMainComponent().add(scrollPane, BorderLayout.CENTER);
		getMainComponent().add(topPanel, BorderLayout.NORTH);
	}

	public void addButtonListener(ActionListener listener) {
		addBudgetButton.addActionListener(listener);
		budgetPopupMenu.addMenuItemListener(listener);
	}

	public JComponent getMainComponent() {
		return mainPanel;
	}

	public int getSelectedRowInModel() {
		return table.convertRowIndexToModel(table.getSelectedRow());
	}

	
	//enhance the design of the table
	private class BudgetTableRenderer extends DefaultTableCellRenderer {
		@Override
		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
			super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
			setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 5));

			if (isSelected) {
				setBackground(table.getSelectionBackground());
			} else {
				setBackground((row % 2 == 0) ? TABLE_COLUMN_COLOR1 : TABLE_COLUMN_COLOR2);
			}

			return this;
		}
	}

	//enhance the design of the month cell
	private class DateRenderer extends BudgetTableRenderer {
		@Override
		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
			super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
			setBorder(noFocusBorder);

			SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT_MONTH);
			GregorianCalendar date = (GregorianCalendar) value;

			setHorizontalAlignment(JLabel.RIGHT);
			setText(dateFormat.format(date.getTime()));

			return this;
		}
	}

	/*private class DoubleRenderer extends BudgetTableRenderer {
		@Override
		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
			super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
			setHorizontalAlignment(JLabel.RIGHT);
			DecimalFormat df = new DecimalFormat("#.##");
			setText(df.format(value));
			return this;
		}
	}*/

	/*private class RemainingBudgetRenderer extends BudgetTableRenderer {
		@Override
		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
			super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
			setBorder(noFocusBorder);

			Double budgetAmount = (Double) table.getValueAt(row, column - 1);
			Double budgetRemain = (Double) table.getValueAt(row, column);

			Double ratio = budgetRemain / budgetAmount;

			setHorizontalAlignment(JLabel.RIGHT);
			DecimalFormat df = new DecimalFormat("#.#");
			setText(df.format(value));

			if (ratio < 0.5) {
				// yellow
				if (ratio < 0.25) {
					// orange
					if (ratio < 0.1) {
						// red
						setBackground(new Color(255, 128, 128));
						setForeground(Color.WHITE);
						return this;
					}
					setBackground(new Color(255, 192, 128));
					setForeground(Color.BLACK);
					return this;
				}
				setBackground(new Color(255, 255, 128));
				setForeground(Color.BLACK);
				return this;
			}
			if (isSelected) {
				setForeground(table.getSelectionForeground());
			} else {
				setForeground(table.getForeground());
			}
			return this;
		}
	}*/

	//Under the ratio cell, there will be 1.bar showing proportion of the budget
	//                                    2.amount of budget and its remaining
	//the color of the bar will change if the remaining is decreasing
	private class BudgetRatioRenderer extends BudgetTableRenderer {
		@Override
		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {

			int ratio = (Integer) value;
			double remaining = (Double) table.getModel().getValueAt(table.convertRowIndexToModel(row), BudgetTableModel.REMAINING);
			double amount = (Double) table.getModel().getValueAt(table.convertRowIndexToModel(row), BudgetTableModel.AMOUNT);
			DecimalFormat df = new DecimalFormat("#.#");

			JLabel label = new JLabel(df.format(remaining) + " / " + df.format(amount), JLabel.TRAILING);


			WebProgressBar bar = new WebProgressBar(JProgressBar.HORIZONTAL, 0, 100);
			bar.setValue(ratio);
			bar.setStringPainted(true);

			Color red = new Color(255, 64, 64);
			Color yellow = new Color(255, 255, 192);
			Color orange = new Color(255, 224, 192);

			if (ratio < 10) {
				bar.setProgressBottomColor(red);
				bar.setProgressTopColor(red);
				bar.setHighlightDarkWhite(red);
			} else if (ratio < 25) {
				bar.setProgressBottomColor(orange);
				bar.setProgressTopColor(orange);
				bar.setHighlightDarkWhite(orange);
			} else if (ratio < 50) {
				bar.setProgressBottomColor(yellow);
				bar.setProgressTopColor(yellow);
				bar.setHighlightDarkWhite(yellow);
			}

			JPanel panel = new JPanel(new GridLayout(1, 2, 10, 0));
			if (isSelected) {
				panel.setBackground(table.getSelectionBackground());
				label.setForeground(table.getSelectionForeground());
			} else {
				panel.setBackground((row % 2 == 0) ? TABLE_COLUMN_COLOR1 : TABLE_COLUMN_COLOR2);
			}
			panel.add(label);
			panel.add(bar);
			return panel;
		}
	}

	private class TableMouseAdapter extends MouseAdapter {

		private JTable table;

		public TableMouseAdapter(JTable table) {
			this.table = table;
		}

		@Override
		public void mousePressed(MouseEvent e) {
			if (e.getButton() == MouseEvent.BUTTON3) {
				Point point = e.getPoint();
				int currentRow = table.rowAtPoint(point);
				if (currentRow != -1)
					table.setRowSelectionInterval(currentRow, currentRow);
			}
		}
	}
}
